package obecto.task.wrapper
{
	import flash.events.ProgressEvent;
	import flash.utils.setTimeout;
	
	import obecto.event.TaskEvent;
	import obecto.event.TaskEventKind;
	import obecto.task.BaseInterruptibleTask;
	import obecto.task.IInterruptibleTask;
	import obecto.task.ITask;
	import obecto.utility.Listener;
	
	[DefaultProperty(name="wrappedTask")]
	public class TaskWrapper extends BaseInterruptibleTask
	{
		protected var progressListener : Listener;
		protected var completeListener : Listener;

		[Bindable]
		public var autoStart : Boolean = true;

		[Bindable]
		public var autoCompleteIfNoWrappedTask : Boolean = false;

		protected var _wrappedTask : ITask;
		public function get wrappedTask() : ITask
		{
			return _wrappedTask;
		}
		public function set wrappedTask(value : ITask) : void
		{
			if(_wrappedTask != value)
			{
				_wrappedTask = value;
				
				stopListeners();
				
				if(_wrappedTask != null)
				{
					progressListener = Listener.create(_wrappedTask, ProgressEvent.PROGRESS,
						handleWrappedTaskProgress, null, false, true, false);
	
					completeListener = Listener.create(_wrappedTask, TaskEvent.COMPLETE,
						handleWrappedTaskComplete, null, false, true, false);
				}
				
				if (_running && !wrappedTask.running && autoStart)
				{
					startListeners();
					wrappedTask.start();
				}
			}
		}
		
		public function TaskWrapper(task : ITask = null)
		{
			super();
			
			wrappedTask = task;
		}
	
		override protected function startActual() : void
		{	
			if(wrappedTask != null)
			{
				startListeners();
				wrappedTask.start();
			}
			else if(autoCompleteIfNoWrappedTask)
			{
				setTimeout(complete, 5);					
			}
		}
		
		override public function end() : void
		{
			if(wrappedTask is IInterruptibleTask)
			{
				IInterruptibleTask(wrappedTask).end();
			}			
			
			stopListeners();
			super.end();
		}
		
		override public function interrupt() : void
		{
			if(wrappedTask is IInterruptibleTask)
			{
				IInterruptibleTask(wrappedTask).interrupt();
			}
			
			stopListeners();
			super.interrupt();
		}
		
		override protected function reverseActual() : void
		{
			if(wrappedTask is IInterruptibleTask)
			{
				IInterruptibleTask(wrappedTask).reverse();
			}
		}
		
		override protected function forwardActual() : void
		{
			if(wrappedTask is IInterruptibleTask)
			{
				IInterruptibleTask(wrappedTask).forward();
			}
		}

		override public function rollback() : void
		{
			if(wrappedTask is IInterruptibleTask)
			{
				IInterruptibleTask(wrappedTask).rollback();
			}
			
			stopListeners();
			super.rollback();
		}	
		
		protected function handleWrappedTaskProgress(event : ProgressEvent) : void
		{
			dispatchEvent(event);
		}
		
		protected function handleWrappedTaskComplete(event : TaskEvent) : void
		{
			stopListeners();
			
			if(event.kind == TaskEventKind.REVERSE)
			{
				completeReverse();
			}
			else
			{
				complete();
			}
		}
		
		protected function startListeners() : void 
		{
			if(progressListener != null && !progressListener.listening)
			{
				progressListener.start();
			}
			
			if(completeListener != null && !completeListener.listening)
			{
				completeListener.start();
			}
		}
		
		protected function stopListeners() : void
		{
			if(progressListener != null && progressListener.listening)
			{
				progressListener.stop();
				//progressListener = null;
			}
			
			if(completeListener != null && completeListener.listening)
			{
				completeListener.stop();
				//completeListener = null;
			}
		}
	}
}